package com.ding.easycontroller.utils;

import com.ding.easycontroller.filter.HandlerFilter;
import com.ding.easycontroller.helper.EcBufferRequest;
import com.ding.easycontroller.helper.EcBufferResponse;
import com.ding.easycontroller.helper.EcRequest;
import com.google.common.base.Joiner;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 请求辅助单元
 */
public class RequestUtils {


    private static HandlerFilter handlerFilter;

    public static void setHandlerFilter(HandlerFilter handlerFilter) {
        RequestUtils.handlerFilter = handlerFilter;
    }

    public static EcBufferRequest transferBufferRequest(EcRequest request) throws IOException {
        return new EcBufferRequest(request);
    }

    private static RestTemplate restTemplate = new RestTemplate();

    public static EcBufferResponse go(Map<String, Object> req) {
        String url = (String) req.get("url");
        String method = (String) req.get("method");
        String body = (String) req.get("body");
        Map<String, String> params = (Map<String, String>) req.get("params");
        Map<String, String> heads = (Map<String, String>) req.get("heads");
        if (url == null) {
            throw new RuntimeException("不存在url");
        }
        if (method == null) {
            method = "GET";
        }
        method = method.toUpperCase();
        URI uri = URI.create(url);

        if (uri.getHost() == null && uri.getPort() == -1 && uri.getScheme() == null) {

            try {
                MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();

                if (params != null) {
                    List<String> strings = new ArrayList<>();
                    for (String s : params.keySet()) {
                        strings.add(s + "=" + params.get(s));
                    }
                    String join = Joiner.on("&").join(strings);

                    if (uri.getQuery() == null) {
                        url += "?" + join;
                    } else {
                        url += "&" + join;
                    }
                }

                mockHttpServletRequest.setRequestURI(url);

                mockHttpServletRequest.setRequestURI(url);

                mockHttpServletRequest.setMethod(method);

                if (heads != null) {
                    heads.forEach(mockHttpServletRequest::addHeader);
                }

                if (body != null) {

                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(byteArrayOutputStream);

                    outputStreamWriter.write(body);

                    outputStreamWriter.flush();

                    mockHttpServletRequest.setContent(byteArrayOutputStream.toByteArray());

                }

                EcBufferResponse ecBufferResponse = ResponseUtils.transferReadableResponse(new MockHttpServletResponse());

                handlerFilter.doFilter(mockHttpServletRequest, ecBufferResponse, new MockFilterChain());

                return ecBufferResponse;

            } catch (IOException | ServletException e) {
                e.printStackTrace();
            }

        } else {

            if (params != null) {
                List<String> strings = new ArrayList<>();
                for (String s : params.keySet()) {
                    strings.add(s + "=" + params.get(s));
                }
                String join = Joiner.on("&").join(strings);

                if (uri.getQuery() == null) {
                    uri = URI.create(uri.toString() + "?" + join);
                } else {
                    uri = URI.create(uri.toString() + "&" + join);
                }
            }


            return restTemplate.execute(uri, HttpMethod.valueOf(method), clientHttpRequest -> {
                HttpHeaders headers = clientHttpRequest.getHeaders();
                if (heads != null) {
                    heads.forEach(headers::add);
                }

                if (body != null) {
                    OutputStream stream = clientHttpRequest.getBody();
                    OutputStreamWriter writer = new OutputStreamWriter(stream);
                    writer.write(body);
                    writer.flush();
                }


            }, clientHttpResponse -> {

                MockHttpServletResponse response = new MockHttpServletResponse();
                response.setStatus(clientHttpResponse.getRawStatusCode());
                HttpHeaders headers = clientHttpResponse.getHeaders();
                for (String s : headers.keySet()) {
                    List<String> list = headers.get(s);
                    if (list != null) {
                        for (String v : list) {
                            response.addHeader(s, v);
                        }
                    }
                }
                InputStream inputStream = clientHttpResponse.getBody();
                EcBufferResponse ecBufferResponse = ResponseUtils.transferReadableResponse(response);

                ServletOutputStream outputStream = ecBufferResponse.getOutputStream();
                StreamUtils.copy(inputStream, outputStream);
                outputStream.flush();


                return ecBufferResponse;
            });
        }

        throw new RuntimeException("无法处理的请求");

    }

}

